package by.home;


import java.util.ArrayList;

import static java.lang.Math.abs;

public class EnvironmentManipulator {

    private Object[][] map;
    private int mapSizeX;
    private int mapSizeY;

    private Point treasureFinder, treasure;

    public void createMap(int mapSizeX, int mapSizeY) {
        this.mapSizeX = mapSizeX;
        this.mapSizeY = mapSizeY;
        map = new Object[mapSizeX][mapSizeY];
    }


    public Object[][] getMap() {
        return map;
    }

    public void createTreasure(int treasurePosX, int treasurePosY) throws PlacingOnMapException {
        Point treasure = new Point("treasure", treasurePosX, treasurePosY);
        if (map[treasurePosX][treasurePosY] == null) {
            map[treasurePosX][treasurePosY] = treasure;
            this.treasure = treasure;
        } else {
            throw new PlacingOnMapException();
        }
    }

    public Point createTreasureFinder(int finderPosX, int finderPosY) throws PlacingOnMapException {
        Point treasureFinder = new Point("finder", finderPosX, finderPosY);
        if (map[finderPosX][finderPosY] == null || (map[finderPosX][finderPosY] != null && ((Point)map[finderPosX][finderPosY]).getObjectType().equals("treasure"))) {
            map[finderPosX][finderPosY] = treasureFinder;
            this.treasureFinder = treasureFinder;
            return treasureFinder;
        } else {
            throw new PlacingOnMapException();
        }
    }

    public void createMountains(int numberOfMountains) {
        int tmpX, tmpY;

        for (int i = 0; i < numberOfMountains; i++) {
            while (true) {
                tmpX = (int) (Math.random() * 10);
                tmpY = (int) (Math.random() * 10);

                if (map[tmpX][tmpY] == null) {
                    map[tmpX][tmpY] = new Point("mountain", tmpX, tmpY);
                    break;
                }
            }
        }
    }

    public Point getTreasureFinder() {
        return this.treasureFinder;
    }

    public boolean moveFinderUp() throws PlacingOnMapException, OutOfMapBordersException {
        if (treasureFinder.getPositionY() + 1 < mapSizeY) {
            if (map[treasureFinder.getPositionX()][treasureFinder.getPositionY() + 1] == null || (map[treasureFinder.getPositionX()][treasureFinder.getPositionY() + 1] != null && ((Point) map[treasureFinder.getPositionX()][treasureFinder.getPositionY() + 1]).getObjectType().equals("treasure"))) {
                map[treasureFinder.getPositionX()][treasureFinder.getPositionY() + 1] = map[treasureFinder.getPositionX()][treasureFinder.getPositionY()];
                map[treasureFinder.getPositionX()][treasureFinder.getPositionY()] = null;
                treasureFinder.setPositionY(treasureFinder.getPositionY() + 1);
                return abs(treasure.getPositionY() - treasureFinder.getPositionY()) < abs(treasure.getPositionY() - treasureFinder.getPositionY() + 1);
            } else {
                throw new PlacingOnMapException();
            }
        } else {
            throw new OutOfMapBordersException();
        }
    }

    public boolean moveFinderDown() throws PlacingOnMapException, OutOfMapBordersException {
        if (treasureFinder.getPositionY() - 1 >= 0) {
            if (map[treasureFinder.getPositionX()][treasureFinder.getPositionY() - 1] == null || (map[treasureFinder.getPositionX()][treasureFinder.getPositionY() + 1] != null && ((Point) map[treasureFinder.getPositionX()][treasureFinder.getPositionY() + 1]).getObjectType().equals("treasure"))) {
                map[treasureFinder.getPositionX()][treasureFinder.getPositionY() - 1] = map[treasureFinder.getPositionX()][treasureFinder.getPositionY()];
                map[treasureFinder.getPositionX()][treasureFinder.getPositionY()] = null;
                treasureFinder.setPositionY(treasureFinder.getPositionY() - 1);
                return abs(treasure.getPositionY() - treasureFinder.getPositionY()) < abs(treasure.getPositionY() - treasureFinder.getPositionY() - 1);
            } else {
                throw new PlacingOnMapException();
            }
        } else {
            throw new OutOfMapBordersException();
        }
    }

    public boolean moveFinderLeft() throws PlacingOnMapException, OutOfMapBordersException {
        if (treasureFinder.getPositionX() - 1 >= 0) {
            if (map[treasureFinder.getPositionX() - 1][treasureFinder.getPositionX()] == null || (map[treasureFinder.getPositionX() + 1][treasureFinder.getPositionY()] != null && ((Point) map[treasureFinder.getPositionX() + 1][treasureFinder.getPositionY()]).getObjectType().equals("treasure"))) {
                map[treasureFinder.getPositionX() - 1][treasureFinder.getPositionX()] = map[treasureFinder.getPositionX()][treasureFinder.getPositionY()];
                map[treasureFinder.getPositionX()][treasureFinder.getPositionY()] = null;
                treasureFinder.setPositionX(treasureFinder.getPositionX() - 1);
                return abs(treasure.getPositionX() - treasureFinder.getPositionX()) < abs(treasure.getPositionX() - treasureFinder.getPositionX() - 1);
            } else {
                throw new PlacingOnMapException();
            }
        } else {
            throw new OutOfMapBordersException();
        }
    }

    public boolean moveFinderRight() throws PlacingOnMapException, OutOfMapBordersException {
        if (treasureFinder.getPositionX() + 1 < mapSizeX) {
            if (map[treasureFinder.getPositionX() + 1][treasureFinder.getPositionX()] == null || (map[treasureFinder.getPositionX() - 1][treasureFinder.getPositionY()] != null && ((Point) map[treasureFinder.getPositionX() - 1][treasureFinder.getPositionY()]).getObjectType().equals("treasure"))) {
                map[treasureFinder.getPositionX() + 1][treasureFinder.getPositionX()] = map[treasureFinder.getPositionX()][treasureFinder.getPositionY()];
                map[treasureFinder.getPositionX()][treasureFinder.getPositionY()] = null;
                treasureFinder.setPositionX(treasureFinder.getPositionX() + 1);
                return abs(treasure.getPositionX() - treasureFinder.getPositionX()) < abs(treasure.getPositionX() - treasureFinder.getPositionX() + 1);
            } else {
                throw new PlacingOnMapException();
            }
        } else {
            throw new OutOfMapBordersException();
        }
    }


    public boolean checkIfFounderFoundTheTreasure() {
        return treasure.getPositionX() == treasureFinder.getPositionX() && treasure.getPositionY() == treasureFinder.getPositionY();
    }
}
